package com.cskaoyan.search.service.impl;

import com.cskaoyan.mall.dto.ProductDto;
import com.cskaoyan.search.converter.ProductConverter;
import com.cskaoyan.search.dto.SearchResponse;
import com.cskaoyan.search.entity.ItemDocument;
import com.cskaoyan.search.form.SearchRequest;
import com.cskaoyan.search.repository.ProductRepository;
import com.cskaoyan.search.service.ProductSearchService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName ProductSearchServiceImpl
 * @Description TODO
 * @Author XiaoWJ
 * @Date 2022/9/27 20:52
 **/
@Slf4j
@Service
public class ProductSearchServiceImpl implements ProductSearchService {

    @Autowired
    ProductConverter productConverter;

    @Autowired
    ProductRepository productRepository;

    @Autowired
    ElasticsearchRestTemplate restTemplate;


    /***
     *  根据条件搜索商品
     * @param request request
     * @return
     */
    @Override
    public SearchResponse search(SearchRequest request) {

        log.info("搜索内容：" + request.getKey()+",排序：" + request.getSort()
        +",分页大小："+request.getSize() + ",页码：" + request.getPage() +
                ",价格区间：(" + request.getPriceGt() + "," + request.getPriceLte()+ "]");

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

       /* MatchQueryBuilder titleQuery = QueryBuilders.matchQuery("title", request.getKey());

        MatchQueryBuilder sellPointQuery = QueryBuilders.matchQuery("sellPoint", request.getKey());

        boolQueryBuilder.should(titleQuery);
        boolQueryBuilder.should(sellPointQuery);*/

        QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(request.getKey()).field("title").field("sellPoint");

        boolQueryBuilder.filter(queryStringQueryBuilder);

        // 价格区间的查询
        Integer priceGt = request.getPriceGt();
        Integer priceLte = request.getPriceLte();

        if (priceGt != null || priceLte != null) {
            RangeQueryBuilder priceRangeQuery =
                    QueryBuilders.rangeQuery("price");

            if (priceGt != null) {
                priceRangeQuery.gt(priceGt);
            }
            if (priceLte != null) {

                priceRangeQuery.lte(priceLte);
            }
            boolQueryBuilder.filter(priceRangeQuery);

        }


        queryBuilder.withQuery(boolQueryBuilder);

        // 构建分页参数

        // 构建排序参数
        Sort sort = null;
        if ("1".equals(request.getSort())) {
            sort = Sort.by(Sort.Order.asc("price"));
        } else if ("-1".equals(request.getSort())) {
            sort = Sort.by(Sort.Order.desc("price"));
        }

        PageRequest pageRequest = null;
        if (sort == null) {
            pageRequest = PageRequest.of(request.getPage() - 1, request.getSize());

        } else {
            pageRequest = PageRequest.of(request.getPage() - 1, request.getSize(), sort);
        }

        queryBuilder.withPageable(pageRequest);
        // 构建高亮参数
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title").field("sellPoint").preTags("<font color='red'>").postTags(" </font>");

        queryBuilder.withHighlightBuilder(highlightBuilder);

        SearchHits<ItemDocument> search = restTemplate.search(queryBuilder.build(), ItemDocument.class);

        long total = search.getTotalHits();

        List<SearchHit<ItemDocument>> searchHits = search.getSearchHits();

        List<ProductDto> productDtos = new ArrayList<>();

        searchHits.forEach(searchHit -> {
            ItemDocument content = searchHit.getContent();


            if (searchHit.getHighlightField("title").size() > 0) {
                content.setTitle(searchHit.getHighlightField("title").get(0));
            }
            if (searchHit.getHighlightField("sellPoint").size() > 0) {
                content.setSellPoint(searchHit.getHighlightField("sellPoint").get(0));
            }
            ProductDto productDto = productConverter.item2Dto(content);
            productDtos.add(productDto);
        });

        SearchResponse<ProductDto> productDtoSearchResponse = new SearchResponse<>();

        productDtoSearchResponse.setData(productDtos);
        productDtoSearchResponse.setTotal(total);

        return productDtoSearchResponse;
    }

    /***
     * 近似匹配搜索框数据
     * @param request request
     * @return
     */

    @Override
    public SearchResponse fuzzySearch(SearchRequest request) {

        PageRequest pageRequest = PageRequest.of(request.getPage() - 1, request.getSize());

        Page<ItemDocument> pageDocuments = productRepository.shouldSearch(request.getKey(), pageRequest);

        List<ProductDto> productDtos = productConverter.items2Dto(pageDocuments.getContent());

        SearchResponse<ProductDto> productDtoSearchResponse = new SearchResponse<>();

        productDtoSearchResponse.setTotal(pageDocuments.getTotalElements());
        productDtoSearchResponse.setData(productDtos);

        return productDtoSearchResponse;

    }


}
